# SPDX-License-Identifier: BSD-2-Clause

import os

from migen import *
from litex.gen import *
from litex.soc.interconnect import wishbone

#from litex.build.io import SDRTristate
from migen.fhdl.specials import Tristate

# IIC Wishbone -----------------------------------------------------------------------------------------

class IIC(LiteXModule):
    def __init__(self, platform, pads):

        self.pads    = pads
        self.wb_ctrl = wb_ctrl = wishbone.Interface(data_width=32, address_width=32, addressing="word")

        self.interrupt = Signal()

        # IIC IOs.
        iic_ios = Record([
            ("scl_i", 1), ("scl_o", 1), ("scl_oe", 1),
            ("sda_i", 1), ("sda_o", 1), ("sda_oe", 1),
        ])

        # # #

        # IIC Wishbone Core Instance.
        self.specials += Instance(self.get_netlist_name(),
            # Clk / Rst.
            i_wb_clk_i   = ClockSignal("sys"),
            i_wb_rst_i   = ResetSignal("sys"),
            # Wishbone Control.
            i_wb_cyc_i   = wb_ctrl.cyc,
            i_wb_adr_i   = wb_ctrl.adr,
            i_wb_dat_i   = wb_ctrl.dat_w,
            i_wb_sel_i   = wb_ctrl.sel,
            i_wb_we_i    = wb_ctrl.we,
            i_wb_stb_i   = wb_ctrl.stb,
            o_wb_dat_o   = wb_ctrl.dat_r,
            o_wb_ack_o   = wb_ctrl.ack,
            # Interrupt.
            o_wb_inta_o  = self.interrupt,
            # pads.
            i_scl_pad_i     = iic_ios.scl_i,
            o_scl_pad_o     = iic_ios.scl_o,
            o_scl_padoen_o  = iic_ios.scl_oe,
            i_sda_pad_i     = iic_ios.sda_i,
            o_sda_pad_o     = iic_ios.sda_o,
            o_sda_padoen_o  = iic_ios.sda_oe,
        )

        #self.specials += SDRTristate(
        #    io = pads.scl,
        #    o  = iic_ios.scl_o,
        #    oe = iic_ios.scl_oe,
        #    i  = iic_ios.scl_i,
        #)

        #self.specials += SDRTristate(
        #    io = pads.sda,
        #    o  = iic_ios.sda_o,
        #    oe = iic_ios.sda_oe,
        #    i  = iic_ios.sda_i,
        #)

        self.specials += Tristate(pads.scl,
            o  = iic_ios.scl_o,  # I2C uses Pull-ups, only drive low.
            oe = iic_ios.scl_oe, # Drive when oe and sda is low.
            i  = iic_ios.scl_i,
        )

        self.specials += Tristate(pads.sda,
            o  = iic_ios.sda_o,  # I2C uses Pull-ups, only drive low.
            oe = iic_ios.sda_oe, # Drive when oe and sda is low.
            i  = iic_ios.sda_i,
        )

        self.add_sources(platform)

    def get_netlist_name(self):
        return "iic_top" 

    def add_sources(self, platform):

        cdir = os.path.abspath('.')
        vdir = os.path.join(cdir, "IIC_WB", "sim")
        netlist_name = self.get_netlist_name()

        print(f"IIC netlist : {netlist_name}")
        if not os.path.exists(os.path.join(vdir, netlist_name + ".v")):
            self.generate_netlist()

        platform.add_source(os.path.join(vdir,  netlist_name + ".v"), "verilog")

    def generate_netlist(self):
        print(f"Generating IIC netlist")
        sources = []
        sdir = "IIC_WB"
        if not os.path.exists(sdir):
            os.system(f"git clone git://repogit.moditek/i2c_master.git IIC_WB")

        cdir = os.path.abspath('.')

        cmd = 'cd {path} && bash merge_rtl.cmd'.format(
            path=os.path.join(cdir, "IIC_WB", "sim") )
        print("!!! "   + cmd)
        if os.system(cmd) != 0:
            raise OSError('Failed to run merge_rtl.cmd')

